import express from "express";
import qiniu from "qiniu";
import multer from "multer";
import path from "path";
import fs from "fs"; // 用于删除本地文件
import {
  addFile,
  addUsers,
  deleteFile,
  findFile,
  getFileSize,
  ifFindFileById,
  removeUsers,
  reNameFile,
} from "../../Db/db";
import { getFileType } from "../../utils";
import { getIp, sessionValidator } from "../../nextFunction";
import { getUserCount, setUserCount } from "../../Db/redis";

export const fileRouter = express.Router();

// 七牛云配置
const accessKey = "ei6je6bwDCwQKg1VA1Pvove8XPBOGoJ7aTLfiGO8";
const secretKey = "AdiFQqrhoAH5h7ldP4xzAoue7FBWFh99x0mMoPTV";
const bucket = "yanmengs";

// console.log(accessKey, secretKey, bucket);
if (!accessKey || !secretKey || !bucket) {
  console.error("❌ 七牛云配置错误，请检查 .env 文件");
  process.exit(1);
}

// 创建认证对象
const mac = new qiniu.auth.digest.Mac(accessKey, secretKey);

// 设置本地存储路径
const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    const uploadPath = path.join(__dirname, "public");
    if (!fs.existsSync(uploadPath)) {
      fs.mkdirSync(uploadPath, { recursive: true });
    }
    cb(null, uploadPath);
  },
  filename: (req, file, cb) => {
    cb(null, Date.now() + String(file.originalname));
    // cb(null, Date.now() + path.extname(file.originalname));
  },
});

const upload = multer({
  storage: storage,
  fileFilter: (req, file, cb) => {
    // 设置文件原始名称的编码
    file.originalname = Buffer.from(file.originalname, "latin1").toString(
      "utf8"
    );

    // 设置文件字段的编码
    if (file.fieldname) {
      file.fieldname = Buffer.from(file.fieldname, "latin1").toString("utf8");
    }

    cb(null, true);
  },
});

// 生成上传 Token (7.x 版本正确写法)
function uptoken(bucket: string, key: string) {
  const mac = new qiniu.auth.digest.Mac(
    process.env.QINIUACCESS_KEY,
    process.env.QINIUSECRET_KEY
  );

  const options = {
    scope: `${bucket}:${key}`,
    // 这里去掉 callbackUrl
  };

  const putPolicy = new qiniu.rs.PutPolicy(options);
  return putPolicy.uploadToken(mac);
}
// 上传文件接口
fileRouter.post(
  "/upload",
  express.urlencoded({ extended: true, limit: "50mb" }),
  express.json({ limit: "50mb" }),
  upload.single("file"),
  getIp,
  sessionValidator,
  async (req: any, res: any) => {
    const { userIp } = req;
    const ownerId = req.accountId;
    const haveUsed = await getUserCount(ownerId);

    if (!req.file) {
      console.log(userIp + "未上传文件");
      return res.status(200).json({ code: 400, message: "请上传文件" });
    }
    const { accountId } = req.body;

    if (!ownerId || !accountId) {
      console.log(userIp + "参数丢失");
      return res.status(200).json({ code: 400, message: "参数丢失" });
    }
    if (!haveUsed) {
      console.log(userIp + "上传失败" + "---");
      return res.status(200).json({ code: 400, message: "上传失败" });
    }
    //检测user加文件是否超过7GB，是的话返回超过7GB
    if (Number(haveUsed) + req.file.size > 7 * 1024 * 1024 * 1024) {
      console.log(userIp + "超过7GB" + "---");
      return res.status(200).json({ code: 400, message: "超过7GB" });
    } else {
      await setUserCount(ownerId, Number(haveUsed) + req.file.size);
    }
    const localFile = path.join(__dirname, "public", req.file.filename); // 本地文件路径
    const key = req.file.filename; // 七牛云存储的文件名
    const token = uptoken(bucket, key); // 生成上传 Token

    const formUploader = new qiniu.form_up.FormUploader();
    const putExtra = new qiniu.form_up.PutExtra();

    // 设置上传时的编码
    putExtra.mimeType = req.file.mimetype;

    formUploader.putFile(token, key, localFile, putExtra, async (err, ret) => {
      fs.unlink(localFile, (err) => {
        if (err) console.log("删除本地文件失败:" + req.file.filename + err);
      });
      if (!err) {
        // **拼接七牛云 CDN URL**
        const fileUrl = `https://cdn.yanmengsss.xyz/${ret.key}`; // 你的七牛云 CDN 域名

        // **删除本地文件**
        const temp = {
          type: getFileType(req.file.filename).type,
          name: req.file.originalname,
          url: fileUrl,
          extension: getFileType(req.file.filename).extension,
          size: req.file.size,
          owner: ownerId,
          accountId,
          users: [],
          bucketFileId: new Date().getTime().toString() + ret.hash,
        };
        await addFile(temp);
        // **直接返回 URL**
        console.log(userIp + "上传成功" + "---" + fileUrl);
        return res.json({
          url: fileUrl,
          code: 200,
        });
      } else {
        console.log(userIp + "上传失败" + "---" + req.file.originalname);
        return res.status(200).json({ message: "上传失败", error: err });
      }
    });
  }
);
//获取文件
fileRouter.get(
  "/getFile",
  getIp,
  sessionValidator,
  async (req: any, res: any) => {
    const { email, accountId, userIp } = req;
    const { types, searchText, sort, limit } = req.query;
    //   console.log(req.query, "123213");
    const files = await findFile(accountId, email, {
      types,
      searchText,
      sort,
      limit,
    });
    console.log(userIp + "获取文件");
    return res.status(200).json({
      code: 200,
      data: {
        documents: files,
        total: files.length,
      },
    });
  }
);
//文件重命名
fileRouter.post(
  "/renameFile",
  getIp,
  sessionValidator,
  async (req: any, res: any) => {
    const { email, accountId, userIp } = req;
    const { bucketFileId, name, extension } = req.body;

    if (!bucketFileId || !name || !extension) {
      console.log(userIp + "文件重命名参数丢失");
      return res.status(400).json({
        code: 400,
        message: "参数丢失",
      });
    }

    const ifCoundEdit = await ifFindFileById(
      bucketFileId,
      accountId,
      email,
      "reName"
    );
    if (!ifCoundEdit) {
      console.log(userIp + "文件重命名无权操作" + "---" + bucketFileId);
      return res.status(403).json({
        code: 403,
        message: "无权操作",
      });
    }

    try {
      console.log(userIp + "文件重命名成功" + "---" + bucketFileId);
      const newName = name + "." + extension;
      await reNameFile(bucketFileId, newName);
      return res.status(200).json({
        code: 200,
        message: "重命名成功",
      });
    } catch (e) {
      // ✅ 正确的 catch 语法
      console.log(userIp + "文件重命名失败" + "---" + bucketFileId + "---" + e);
      return res.status(200).json({
        code: 500,
        message: "重命名失败",
      });
    }
  }
);
//文件分享
fileRouter.post(
  "/shareFile",
  getIp,
  sessionValidator,
  async (req: any, res: any) => {
    const { email, accountId, userIp } = req;
    const { bucketFileId, users, type } = req.body;
    if (!bucketFileId || !users || !type) {
      console.log(userIp + "文件分享参数丢失");
      return res.status(400).json({
        code: 400,
        message: "参数丢失",
      });
    }
    const ifCoundEdit = await ifFindFileById(
      bucketFileId,
      accountId,
      email,
      "share"
    );
    if (!ifCoundEdit) {
      console.log(userIp + "文件分享无权操作" + "---" + bucketFileId);
      return res.status(403).json({
        code: 403,
        message: "无权操作",
      });
    }

    try {
      if (type === "del") await removeUsers(bucketFileId, users);
      else if (type === "add") await addUsers(bucketFileId, users);
      console.log(
        userIp + "文件" + type === "del"
          ? "取消分享成功"
          : "分享成功" + "---" + bucketFileId + "---" + users
      );
      return res.status(200).json({
        code: 200,
        message: type === "del" ? "取消分享成功" : "分享成功",
      });
    } catch (e) {
      console.log(
        userIp + "文件" + type === "del"
          ? "取消分享失败"
          : "分享失败" + "---" + bucketFileId + "---" + users + "---" + e
      );
      return res.status(200).json({
        code: 500,
        message: "分享失败",
      });
    }
  }
);
//删除文件
fileRouter.delete(
  "/deleteFile",
  getIp,
  sessionValidator,
  async (req: any, res: any) => {
    const { email, accountId, userIp } = req;
    const { bucketFileId } = req.body;
    const haveUsed = await getUserCount(accountId);
    if (!bucketFileId) {
      console.log(
        userIp + email + "---" + accountId + "---" + "删除文件参数丢失"
      );
      return res.status(400).json({
        code: 400,
        message: "参数丢失",
      });
    }
    const size = await getFileSize(bucketFileId);
    if (size === -1) {
      console.log(
        userIp + email + "---" + accountId + "---" + "删除文件参数丢失"
      );
      return res.status(200).json({
        code: 400,
        message: "查无文件",
      });
    }
    await setUserCount(accountId, Number(haveUsed) - size);
    const ifCoundEdit = await ifFindFileById(
      bucketFileId,
      accountId,
      email,
      "delete"
    );
    if (!ifCoundEdit) {
      console.log(
        userIp + email + "---" + accountId + "---" + "删除文件无权操作"
      );
      return res.status(403).json({
        code: 403,
        message: "无权操作",
      });
    }

    try {
      await deleteFile(bucketFileId);
      console.log(userIp + email + "---" + accountId + "---" + "删除文件成功");
      return res.status(200).json({
        code: 200,
        message: "删除成功",
      });
    } catch {
      (e) => {
        console.log(
          userIp +
            email +
            "---" +
            accountId +
            "---" +
            "删除文件失败" +
            "---" +
            e
        );
        return res.status(200).json({
          code: 500,
          message: "删除失败",
        });
      };
    }
  }
);
//获取文件概览
fileRouter.get(
  "/getFileOverview",
  getIp,
  sessionValidator,
  async (req: any, res: any) => {
    const { email, accountId, userIp } = req;
    const totalSpace = {
      image: { size: 0, latestDate: "" },
      document: { size: 0, latestDate: "" },
      video: { size: 0, latestDate: "" },
      audio: { size: 0, latestDate: "" },
      other: { size: 0, latestDate: "" },
      used: 0,
      all: 2 * 1024 * 1024 * 1024 /* 2GB available bucket storage */,
    };
    try {
      //时间倒序
      let options = {
        sort: "createdAt-asc",
      };
      const files = await findFile(accountId, email, options);
      files.forEach((file: any) => {
        totalSpace[file.type].size += file.size;
        totalSpace[file.type].latestDate = file.updatedAt;
        totalSpace.used += file.size;
      });
      console.log(userIp + "获取文件概览成功");
      return res.status(200).json({
        code: 200,
        data: totalSpace,
      });
    } catch (e) {
      console.log(userIp + "获取文件概览失败:" + "---" + e);
      return res.status(200).json({
        code: 500,
        message: "获取文件失败",
      });
    }
  }
);
